home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Skunkware 5
/
Skunkware 5.iso
/
src
/
Games
/
xsokoban
/
xdisp.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-05-03
|
14KB
|
621 lines
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include <stdio.h>
#include "sokoban.h"
#include "help.h"
#define PRG_NAME "xsokoban"
#define BIT_H 30
#define BIT_W 30
#define FONT "9x15"
#define DEF_CURSOR 102
#define HELPLINE ((BIT_H * MAXROW) + 30)
#define STATUSLINE ((BIT_H * MAXROW) + 5)
#define HELP_H (BIT_H*MAXROW)
#define HELP_W (BIT_W*MAXCOL)
extern short rows, cols, level, moves, pushes, packets, savepack;
extern char map[MAXROW+1][MAXCOL+1];
extern char bitfilepath[1024];
extern int optbitmap, optwalls;
char *wallname[] =
{ "lonewall.xbm",
"southwall.xbm",
"westwall.xbm",
"llcrnrwall.xbm",
"northwall.xbm",
"vertiwall.xbm",
"ulcrnrwall.xbm",
"west_twall.xbm",
"eastwall.xbm",
"lrcrnrwall.xbm",
"horizwall.xbm",
"s_twall.xbm",
"urcrnrwall.xbm",
"east_twall.xbm",
"n_twall.xbm",
"centerwall.xbm" };
Pixmap goal, man, object, treasure, swalls[16], blank, work, help[2];
Pixmap floor, saveman;
Display *display;
Window win;
int screen;
GC gc, rev, depth_rev;
XFontStruct *font_info;
unsigned int width, height, depth;
char buf[100];
int display_alloc = 0, font_alloc = 0, gc_alloc = 0, pix_alloc = 0;
Colormap cmap;
Cursor this_curs;
XColor foreg, backg, curs, bordr;
int hlpscrn = -1;
void get_int(res, val, def_val)
char *res;
int *val, def_val;
{
char *string;
string = XGetDefault(display, PRG_NAME, res);
if(string)
*val = atoi(string);
else
*val = def_val;
}
void get_string(res, val, def_val)
char *res;
char **val;
char *def_val;
{
char *string;
string = XGetDefault(display, PRG_NAME, res);
if(string) {
*val = string;
} else {
*val = def_val;
}
}
int get_color(res, val, def_val)
char *res;
XColor *val;
char *def_val;
{
char *string;
int found = False;
string = XGetDefault(display, PRG_NAME, res);
if(string)
if(XParseColor(display, cmap, string, val))
found = True;
if(!found)
if(XParseColor(display, cmap, def_val, val))
found = True;
if(!found)
return 0;
if(!XAllocColor(display, cmap, val))
return 0;
return 1;
}
int init_screen()
{
int i;
char *win_name = "XSokoban";
char *icon_name = "XSokoban";
XSizeHints size_hints;
XWMHints wm_hints;
XSetWindowAttributes win_attr;
XClassHint classhint;
XGCValues revvals, values;
XTextProperty Win_Name, Icon_Name;
char *font_name;
char *string;
int temp, tempwalls = 1;
if((display = XOpenDisplay(NULL)) == NULL) {
return E_NODISPLAY;
}
display_alloc = 1;
get_string("fontname", &font_name, FONT);
if((font_info = XLoadQueryFont(display, font_name)) == NULL) {
return E_NOFONT;
}
font_alloc = 1;
screen = DefaultScreen(display);
cmap = DefaultColormap(display, screen);
depth = DefaultDepth(display, screen);
if(!get_color("foreground", &foreg, "white"))
return E_NOCOLOR;
if(!get_color("background", &backg, "black"))
return E_NOCOLOR;
if(!get_color("border", &bordr, "white"))
return E_NOCOLOR;
if(!get_color("cursor", &curs, "white"))
return E_NOCOLOR;
if(!optbitmap) {
get_string("bitmaps", &string, NULL);
if(string) {
strcpy(bitfilepath, string);
optbitmap = 1;
tempwalls = 0;
}
}
if(!optwalls || !tempwalls) {
get_int("fancyWalls", &optwalls, tempwalls);
}
width = MAXCOL * BIT_W;
height = MAXROW * BIT_H + 50;
size_hints.min_width = size_hints.width = size_hints.max_width = width;
size_hints.min_height = size_hints.height = size_hints.max_height = height;
size_hints.x = size_hints.y = 0;
size_hints.flags = (PSize | PPosition | PMinSize | PMaxSize);
wm_hints.initial_state = NormalState;
wm_hints.input = True;
wm_hints.flags = (StateHint | InputHint);
classhint.res_class = classhint.res_name = PRG_NAME;
this_curs = XCreateFontCursor(display, DEF_CURSOR);
XRecolorCursor(display, this_curs, &curs, &backg);
win_attr.background_pixel = backg.pixel;
win_attr.border_pixel = bordr.pixel;
win_attr.backing_store = Always;
win_attr.event_mask = (KeyPressMask | ExposureMask);
win_attr.cursor = this_curs;
if(XStringListToTextProperty(&win_name, 1, &Win_Name) == NULL) {
return E_NOMEM;
}
if(XStringListToTextProperty(&icon_name, 1, &Icon_Name) == NULL) {
return E_NOMEM;
}
win = XCreateWindow(display, RootWindow(display, screen), 0, 0, width,
height, 4, CopyFromParent, InputOutput, CopyFromParent,
(CWBackPixel | CWBorderPixel | CWBackingStore |
CWEventMask | CWCursor), &win_attr);
XSetWMNormalHints(display, win, &size_hints);
XSetWMHints(display, win, &wm_hints);
XSetClassHint(display, win, &classhint);
XSetWMName(display, win, &Win_Name);
XSetWMIconName(display, win, &Icon_Name);
for(i = 0; i < 2; i++) {
help[i] = XCreatePixmap(display, win, HELP_W, HELP_H, depth);
}
blank = XCreatePixmap(display, win, BIT_W, BIT_H, 1);
work = XCreatePixmap(display, win, width, height, depth);
values.foreground = foreg.pixel;
revvals.foreground = backg.pixel;
values.background = backg.pixel;
revvals.background = foreg.pixel;
values.function = revvals.function = GXcopy;
values.font = revvals.font = font_info->fid;
gc = XCreateGC(display, win, (GCFunction | GCBackground | GCForeground |
GCFont), &values);
rev = XCreateGC(display, blank, (GCFunction | GCBackground | GCForeground |
GCFont), &revvals);
depth_rev = XCreateGC(display, win, (GCFunction | GCBackground |
GCForeground | GCFont), &revvals);
gc_alloc = 1;
if(load_bitmaps() == E_NOBITMAP) return E_NOBITMAP;
make_help_windows();
pix_alloc = 1;
XFillRectangle(display, blank, rev, 0, 0, BIT_W, BIT_H);
clearscreen();
XMapWindow(display, win);
redisp_screen();
return 0;
}
load_one_bitmap(fname, altname, this_pix)
char *fname;
char *altname;
Pixmap *this_pix;
{
unsigned int dummy1, dummy2;
int dummy3, dummy4;
int load_fail;
if(optbitmap) {
chdir(bitfilepath);
if(XReadBitmapFile(display, win, fname, &dummy1, &dummy2, this_pix,
&dummy3, &dummy4) != BitmapSuccess) {
if(altname && *altname) {
printf("Unable to load %s/%s, trying alternate %s/%s\n",
bitfilepath, fname, bitfilepath, altname);
if(XReadBitmapFile(display, win, altname, &dummy1, &dummy2, this_pix,
&dummy3, &dummy4) != BitmapSuccess) {
load_fail = 1;
printf("Unable to load alternate %s/%s, trying defaults\n",
bitfilepath, altname);
} else {
return 0;
}
} else {
printf("Unable to load %s/%s, trying defaults.\n", bitfilepath, fname);
}
} else
return 0;
}
chdir(BITPATH);
if(!optbitmap || load_fail) {
if(XReadBitmapFile(display, win, fname, &dummy1, &dummy2, this_pix,
&dummy3, &dummy4) != BitmapSuccess) {
if(altname && *altname) {
printf("Unable to load default %s, trying alternate %s\n",
fname, altname);
if(XReadBitmapFile(display, win, altname, &dummy1, &dummy2, this_pix,
&dummy3, &dummy4) != BitmapSuccess) {
printf("Unable to load alternate %s!\n", altname);
return 1;
} else
return 0;
} else {
printf("Unable to load default %s!\n", fname);
return 1;
}
} else
return 0;
}
}
int load_bitmaps()
{
register int i;
int ret = 0;
if(load_one_bitmap("man.xbm", NULL, &man)) ret = E_NOBITMAP;
if(load_one_bitmap("saveman.xbm", "man.xbm", &saveman)) ret = E_NOBITMAP;
if(load_one_bitmap("object.xbm", NULL, &object)) ret = E_NOBITMAP;
if(load_one_bitmap("treasure.xbm", NULL, &treasure)) ret = E_NOBITMAP;
if(load_one_bitmap("goal.xbm", NULL, &goal)) ret = E_NOBITMAP;
if(load_one_bitmap("floor.xbm", NULL, &floor)) ret = E_NOBITMAP;
if(optwalls) {
for(i = 0; i < 16; i++) {
if(load_one_bitmap(wallname[i], "wall.xbm", &swalls[i])) ret = E_NOBITMAP;
}
} else {
if(load_one_bitmap("wall.xbm", NULL, &swalls[0])) ret = E_NOBITMAP;
}
return ret;
}
make_help_windows()
{
int i;
char *title =
" Sokoban -- X version by Joseph L. Traub -- Help page %d";
char *next =
" Press Enter to exit -- Any other key for next page.";
for (i = 0; i < 2; i++) {
XFillRectangle(display, help[i], depth_rev, 0, 0, HELP_W, HELP_H);
sprintf(buf, title, (i+1));
XDrawImageString(display, help[i], gc, 0, 11, buf, strlen(buf));
XDrawLine(display, help[i], gc, 0, 17, HELP_W, 17);
XDrawLine(display, help[i], gc, 0, HELP_H-20, HELP_W, HELP_H-20);
XDrawImageString(display, help[i], gc, 2, HELP_H-7, next, strlen(next));
}
for(i = 0; help_pages[i].textline != NULL; i++) {
XDrawImageString(display,help[help_pages[i].page], gc,
help_pages[i].xpos * (font_info->max_bounds.width),
help_pages[i].ypos, help_pages[i].textline,
strlen(help_pages[i].textline));
}
XCopyPlane(display, man, help[0], gc, 0, 0, BIT_W, BIT_H, 180, 360, 1);
XCopyPlane(display, goal, help[0], gc, 0, 0, BIT_W, BIT_H, 270, 360, 1);
XCopyPlane(display, swalls[0], help[0], gc, 0, 0, BIT_W, BIT_H, 369, 360, 1);
XCopyPlane(display, object, help[0], gc, 0, 0, BIT_W, BIT_H, 477, 360, 1);
XCopyPlane(display, treasure, help[0], gc, 0, 0, BIT_W, BIT_H, 270, 400, 1);
XCopyPlane(display, saveman, help[0], gc, 0, 0, BIT_W, BIT_H, 477, 400, 1);
}
shutdown_screen() {
int i;
if(font_alloc) {
XFreeFont(display, font_info);
}
if(gc_alloc) {
XFreeGC(display, gc);
XFreeGC(display, rev);
XFreeGC(display, depth_rev);
}
if(pix_alloc) {
XFreePixmap(display, work);
XFreePixmap(display, man);
XFreePixmap(display, saveman);
XFreePixmap(display, goal);
XFreePixmap(display, treasure);
XFreePixmap(display, object);
XFreePixmap(display, floor);
for(i = 0; i < 16; i++) {
if(i < 2)
XFreePixmap(display, help[i]);
if(i == 0 || optwalls)
XFreePixmap(display, swalls[i]);
}
XFreePixmap(display, blank);
}
if(display_alloc)
XCloseDisplay(display);
}
clearscreen() {
int i,j;
XFillRectangle(display, work, depth_rev, 0, 0, width, height);
for(i = 0; i < MAXROW; i++)
for(j = 0; j < MAXCOL; j++)
XCopyPlane(display, floor, work, gc, 0, 0, BIT_W, BIT_H, j*BIT_W,
i*BIT_H, 1);
XDrawLine(display, work, gc, 0, BIT_H*MAXROW, BIT_W*MAXCOL, BIT_H*MAXROW);
}
char event_loop()
{
XEvent report;
char buf[1];
int bufsiz = 1;
KeySym keysym;
XComposeStatus compose;
int cntrl, shiftd;
while(1) {
XNextEvent(display, &report);
switch (report.type) {
case Expose:
redisp_screen();
break;
case KeyPress:
buf[0] = NULL;
(void) XLookupString(&report.xkey, buf, bufsiz, &keysym, &compose);
cntrl = report.xkey.state & ControlMask;
shiftd = report.xkey.state & ShiftMask;
if(keysym == XK_Left) {
if (cntrl)
buf[0] = '\010';
else if (shiftd)
buf[0] = 'H';
else
buf[0] = 'h';
}
if(keysym == XK_Right) {
if (cntrl)
buf[0] = '\014';
else if (shiftd)
buf[0] = 'L';
else
buf[0] = 'l';
}
if(keysym == XK_Up) {
if (cntrl)
buf[0] = '\013';
else if (shiftd)
buf[0] = 'K';
else
buf[0] = 'k';
}
if(keysym == XK_Down) {
if (cntrl)
buf[0] = '\012';
else if (shiftd)
buf[0] = 'J';
else
buf[0] = 'j';
}
if(*buf)
return buf[0];
break;
default:
break;
}
}
}
int redisp_screen() {
if(hlpscrn == -1)
XCopyArea(display, work, win, gc, 0, 0, width, height, 0, 0);
else {
XCopyArea(display, help[hlpscrn], win, gc, 0, 0, HELP_W, HELP_H, 0, 0);
}
XFlush(display);
}
int showscreen() {
int mapchar();
register short i, j;
for(i = 0; i < rows; i++)
for(j = 0; j < cols && map[i][j] != '\0'; j++)
mapchar(map[i][j], i, j);
displevel();
disppackets();
dispsave();
dispmoves();
disppushes();
disphelp();
redisp_screen();
}
int mapchar(c, i, j)
char c;
register short i, j;
{
Pixmap this, get_obj_adr();
register short offset_row, offset_col;
offset_col = BIT_W * (((MAXCOL - cols) / 2) + j);
offset_row = BIT_H * (((MAXROW - rows) / 2) + i);
this = get_obj_adr(i, j, c);
XCopyPlane(display, this, work, gc, 0, 0, BIT_W, BIT_H, offset_col,
offset_row, 1);
}
Pixmap get_obj_adr(i, j, c)
register short i, j;
char c;
{
switch (c) {
case player:
return man;
case playerstore:
return saveman;
case store:
return goal;
case save:
return treasure;
case packet:
return object;
case wall:
if(optwalls)
return swalls[pickwall(i,j)];
else
return swalls[0];
case ground:
return floor;
default:
return blank;
}
}
pickwall(i, j)
int i, j;
{
int ret = 0;
if(i > 0 && map[i-1][j] == wall)
ret += 1;
if(i < rows && map[i+1][j] == wall)
ret += 4;
if(j < cols && map[i][j+1] == wall)
ret += 2;
if (j > 0 && map[i][j-1] == wall)
ret += 8;
return ret;
}
draw_string(x, y, text)
int x, y;
char *text;
{
int x_offset, y_offset;
x_offset = x * font_info->max_bounds.width;
y_offset = y + font_info->ascent;
XDrawImageString(display, work, gc, x_offset, y_offset, text, strlen(text));
}
clear_string(x, y, len)
int x, y, len;
{
int i;
for(i = 0; i < len; i++)
buf[i] = ' ';
buf[len] = '\0';
draw_string(x, y, buf);
}
displevel()
{
sprintf(buf, "Level: %3d", level);
draw_string(0, STATUSLINE, buf);
}
disppackets()
{
sprintf(buf, "Packets: %3d", packets);
draw_string(12, STATUSLINE, buf);
}
dispsave()
{
sprintf(buf, "Saved: %3d", savepack);
draw_string(26, STATUSLINE, buf);
}
dispmoves()
{
sprintf(buf, "Moves: %5d", moves);
draw_string(38, STATUSLINE, buf);
}
disppushes()
{
sprintf(buf, "Pushes: %3d", pushes);
draw_string(52, STATUSLINE, buf);
}
disphelp()
{
draw_string(0, HELPLINE, "Press ? for help.");
}
showhelp()
{
int i = 0;
char c;
hlpscrn = 0;
XCopyArea(display, help[i], win, gc, 0, 0, HELP_W, HELP_H, 0, 0);
XFlush(display);
while(c = event_loop()) {
switch(c) {
case '\015':
hlpscrn = -1;
return;
default:
i = (i+1)%2;
hlpscrn = i;
XCopyArea(display, help[i], win, gc, 0, 0, HELP_W, HELP_H, 0, 0);
XFlush(display);
}
}
}
helpmessage()
{
XBell(display,0);
redisp_screen();
}